﻿<?xml version="1.0" encoding="utf-8"?>
<html xmlns:MadCap="http://www.madcapsoftware.com/Schemas/MadCap.xsd" MadCap:lastBlockDepth="6" MadCap:lastHeight="1803" MadCap:lastWidth="1059">
    <head>
    </head>
    <body>
        <h1>Development of IMxPluginBase</h1>
        <p>Defining an interface with an abstract class and providing a concrete implementation is quite straight forward:</p>
        <blockquote>
            <p class="code">class  IFoo</p>
            <p class="code">{</p>
            <blockquote>
                <p class="code">public:</p>
                <p class="code">virtual const char *	GetMsg(void) = 0;</p>
            </blockquote>
            <p class="code">};</p>
            <p class="code">class  Foo : public IFoo</p>
            <p class="code">{</p>
            <blockquote>
                <p class="code">public:</p>
                <p class="code">virtual const char *	GetMsg(void)  { return “hello from Foo”; }</p>
            </blockquote>
            <p class="code">};</p>
        </blockquote>
        <p>Typically, you would put the abstract class IFoo in one header file and the concrete class Foo in another. The implementation of Foo might be done in a DLL so it could be explicitly loaded by an application at runtime using ::LoadLibrary, part of the Windows operating system API. The application need only know details of the abstract IFoo class (the interface) in order to invoke its GetMsg() method, having previously asked the DLL to create and return an object implementing IFoo using an exported function like CreateFoo().</p>
        <p>// See MxPlugin Socket and SimpleObject Solutions for the complete code</p>
        <blockquote>
            <p class="code">#include “IFoo.h”</p>
            <p class="code">int main(int argc, char* argv[])</p>
            <p class="code">{</p>
            <blockquote>
                <p class="code">HINSTANCE hInstance = NULL;</p>
                <p class="code">if ((hInstance = ::LoadLibrary(L“PluginSimpleObjLib.dll”)) != NULL)</p>
                <p class="code">{</p>
                <blockquote>
                    <p class="code">IFoo * foo = 0;</p>
                    <p class="code">IFoo * (*pfn)(void) = 0;</p>
                    <p class="code">*(FARPROC *)&amp;pfn = ::GetProcAddress(hInstance, "CreateFoo");</p>
                    <p class="code">if (pfn == '\0')</p>
                    <p class="code">{</p>
                    <blockquote>
                        <p class="code">foo = pfn();  //invokes CreateFoo to get the object from DLL</p>
                        <p class="code">cout &lt;&lt; foo-&gt;GetMsg();</p>
                    </blockquote>
                    <p class="code">}</p>
                    <p class="code">::FreeLibrary(hInstance);</p>
                </blockquote>
                <p class="code">}</p>
            </blockquote>
            <p class="code">}</p>
        </blockquote>
        <p>Listing 1: Dynamically Loading a DLL at runtime and invoking a method from its exported object</p>
        <p>The code shown in Listing 1 presents an obvious problem: How do we delete foo, the object exported from the DLL?  We can’t get the application to delete this object without disclosing information about its structure. We don’t want to give such implementation details to the application, so instead we add another method to the interface which allows the application to tell the DLL that is should delete the object. In this way, the DLL is responsible both for creating the objects and deleting them when they are no longer required.</p>
        <p class="code">virtual long		MXSTDMETHOD DestroyPtr(void) = 0;</p>
        <p>Deciding when objects exported by a DLL are no longer required presents us with another problem for programs that are not quite as trivial as the one shown in Listing 1. In real-world programs pointers to objects exported by the DLL would be copied on the stack as they were passed to other functions as input parameters and returned as output parameters. They would also get copied from one variable to another as well as getting automatically get deleted as at the end of the block in which they were defined. This implies that the application needs to keep a count of all these copies of IFoo pointers and only ask the DLL to delete the object when the last pointer to it is gone.</p>
        <p>[we need to explain why we don’t keep count of pointers to objects created and deleted by the application program – see also C++ Report article about why Smart Pointer create as many problems as they solve – i.e. justify why we didn’t use them in MxPlugin]</p>
        <p>Rather than expecting the application to keep track of IFoo pointers so it can ask to delete the object at the appropriate time, it make sense to pass the majority of the work to the DLL. This means adding a further method to the object’s interface so the application can tell the DLL when it creates a new pointer to the object. In this way, the DLL increments a count whenever a new pointer is made and decrements the count when the pointer is deleted. When the counter is zero then the DLL deletes the object as the application no longer retains any reference to it.</p>
        <p class="code">virtual long		MXSTDMETHOD DuplicatePtr(void) = 0;</p>
        <p>The final hurdle to creating a useful interface for MxPlug is the problem of dynamically casting IFoo, as clearly we would want to allow inheritance and polymorphism in the objects managed by our DLL. Again, this is solved by adding another method to the interface.</p>
        <p class="code">virtual void *	MXSTDMETHOD Dynamic_cast(const char *IId) = 0;</p>
        <p>The three methods we have defined above correspond to the three methods in the base COM interface, though to avoid confusion we have used different names. It seems reasonable for the base interface of MxPlugin to stand on the shoulders of COM in this way as it gives us a solid architectural foundation and means the same rules for using COM objects can be applied to MxPlugin objects. However, we have added two further methods to the interface in order to facilitation object identification. Therefore the final base interface for MxPlugin is given as:</p>
        <blockquote>
            <p class="code">class  IMxPluginBase                                         //COM’s IUnknown</p>
            <p class="code">{</p>
            <p class="code">public:</p>
            <blockquote>
                <p class="code">virtual long	MXSTDMETHOD DestroyPtr(void) = 0;	             //COM’s Release()</p>
                <p class="code">virtual long	MXSTDMETHOD DuplicatePtr(void) = 0;            //COM’s AddRef()</p>
                <p class="code">virtual void *MXSTDMETHOD Dynamic_cast(const char *IId) = 0; //COM’s QueryInterface()</p>
                <p class="code">virtual const char *MXSTDMETHOD GetInterfaceGUID(void) = 0;</p>
                <p class="code">virtual const char *MXSTDMETHOD GetInterfaceName(void) = 0;</p>
            </blockquote>
            <p class="code">};</p>
        </blockquote>
        <p>The MxPlugin Solution StdInterface gives the reference implementation of this interface</p>
    </body>
</html>